package com.yunsc.common.export;

import cn.hutool.core.text.NamingCase;
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.style.HorizontalCellStyleStrategy;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.BorderStyle;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.apache.poi.ss.usermodel.VerticalAlignment;

import java.lang.reflect.Field;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @version: 1.0
 * @Author: adan
 * @description: 导出工具类
 * @date: 2024-05-29 21:53
 */
@Slf4j
@Data
public class ExportUtil {


    // 自定义表头样式
    public static HorizontalCellStyleStrategy getStyleStrategy() {
        // 头的策略  样式调整
        WriteCellStyle headWriteCellStyle = new WriteCellStyle();
        // 水平对齐方式
        headWriteCellStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 垂直对齐方式
        headWriteCellStyle.setVerticalAlignment(VerticalAlignment.CENTER);
        // 内容的策略
        WriteCellStyle contentStyle = new WriteCellStyle();
        // 设置 水平居中
        contentStyle.setHorizontalAlignment(HorizontalAlignment.CENTER);
        // 设置细边框
        contentStyle.setBorderBottom(BorderStyle.THIN);
        contentStyle.setBorderLeft(BorderStyle.THIN);
        contentStyle.setBorderRight(BorderStyle.THIN);
        contentStyle.setBorderTop(BorderStyle.THIN);
        // 设置边框颜色 25级灰度
        contentStyle.setBottomBorderColor(IndexedColors.BLACK.getIndex());
        contentStyle.setTopBorderColor(IndexedColors.BLACK.getIndex());
        contentStyle.setLeftBorderColor(IndexedColors.BLACK.getIndex());
        contentStyle.setRightBorderColor(IndexedColors.BLACK.getIndex());

        // 这个策略是 头是头的样式 内容是内容的样式 其他的策略可以自己实现
        return new HorizontalCellStyleStrategy(headWriteCellStyle, contentStyle);
    }

    /**
     * 获取excel表头所有字段
     *
     * @param fieldSet   字段集合
     * @param headerName 表头
     * @param userName   导出人
     * @return 表头集合
     */
    public static List<List<String>> setHeadList(List<String> fieldSet, String headerName, String userName) {
        List<List<String>> headTitles = new ArrayList<>();
        userName = "导出人：" + userName;
        // 固定title
        for (String field : fieldSet) {
            List<String> headTitle = new ArrayList<>();
            headTitle.add(headerName);
            headTitle.add(userName);
            headTitle.add(field);
            headTitles.add(headTitle);
        }
        return headTitles;
    }


    /**
     * 反射获取字段名和excel注解信息
     *
     * @param clz        获取的类
     * @param fieldNames 需要导出的字段名
     * @return 字段名和excel注解信息
     */
    public static <T> Set<String> resolveFieldNamesList(Class<T> clz, List<String> fieldNames) {
        Set<String> fieldNamesList = new LinkedHashSet<>();
        List<String> newFieldNames = fieldNames.stream().map(NamingCase::toCamelCase).collect(Collectors.toList());
        try {
            // 得到所有定义字段
            Field[] allFields = clz.getDeclaredFields();
            // 得到所有field并存放到一个list中.
            for (Field field : allFields) {
                // 判断是否是需要的字段
                if (newFieldNames.contains(field.getName())) {
                    // 判断并获取excel注解信息
                    if (field.isAnnotationPresent(ExcelProperty.class)) {
                        ExcelProperty excelProperty = field.getDeclaredAnnotation(ExcelProperty.class);
                        fieldNamesList.add(excelProperty.value()[0]);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return fieldNamesList;
    }

    /**
     * 反射获取字段名和excel注解信息
     *
     * @param clz        获取的类
     * @param fieldNames 需要导出的字段名
     * @return 字段名和excel注解信息
     */
    public static <T> Map<String, String[]> resolveFieldNames(Class<T> clz, List<String> fieldNames) {
        Map<String, String[]> map = new LinkedHashMap<>();
        if (fieldNames == null || fieldNames.isEmpty()){
            return resolveClassFieldNames(clz);
        }
        List<String> newFieldNames = fieldNames.stream().map(NamingCase::toCamelCase).collect(Collectors.toList());
        try {
            // 得到所有定义字段
            Field[] allFields = clz.getDeclaredFields();
            // 得到所有field并存放到一个list中.
            for (Field field : allFields) {
                // 判断是否是需要的字段
                if (newFieldNames.contains(field.getName())) {
                    // 判断并获取excel注解信息
                    if (field.isAnnotationPresent(ExcelProperty.class)) {
                        ExcelProperty excelProperty = field.getDeclaredAnnotation(ExcelProperty.class);
                        map.put(field.getName(), excelProperty.value());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 反射获取类所有字段名和excel注解信息
     *
     * @param clz 获取的类
     * @return 字段名和excel注解信息
     */
    public static <T> Map<String, String[]> resolveClassFieldNames(Class<T> clz) {
        Map<String, String[]> map = new LinkedHashMap<>();
        try {
            // 得到所有定义字段
            Field[] allFields = clz.getDeclaredFields();
            log.info("allFields:{}", allFields);
            // 得到所有field并存放到一个list中.
            for (Field field : allFields) {
                // 判断并获取excel注解信息
                if (field.isAnnotationPresent(ExcelProperty.class)) {
                    ExcelProperty excelProperty = field.getDeclaredAnnotation(ExcelProperty.class);
                    map.put(field.getName(), excelProperty.value());
                }
            }
        } catch (Exception e) {
            log.error("获取字段名失败：{}", e.getMessage());
        }
        return map;
    }



}
